﻿// <copyright file="WebServerCore.cs" company="Maierhofer Software">
//      Copyright (c) 2010 by Maierhofer Software. All rights reserved.
// </copyright>

namespace WAF.Server
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using WAF.Server.Ipc;
    using WAF.Server.Content;
    using WAF.Server.Sessions;

    /// <summary>
    /// Core functions for the app server module. 
    /// Provides content generation factory functions.
    /// </summary>
    public class AppServerCore : IDisposable
    {
        bool isDisposed = true;
        List<IContentGeneratorFactory> factories;
        object factoriesLock = new object();

        /// <summary>
        /// This delegate is used to process (send) the response to the web server module
        /// </summary>
        private ProcessResponseDelegate processResponse;

        /// <summary>
        /// Response processing delegate. 
        /// </summary>
        /// <param name="response">The response.</param>
        public delegate void ProcessResponseDelegate(ContentResponse response );


        /// <summary>
        /// Initializes a new instance of the <see cref="AppServerCore"/> class.
        /// </summary>
        /// <param name="processResponse">The process response delegate.</param>
        public void Init(ProcessResponseDelegate processResponse)
        {
            this.isDisposed = false;
            this.processResponse = processResponse;
            this.factories = new List<IContentGeneratorFactory>();
            Session.StartSessionDisposing();
        }



        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        void Dispose(bool disposing)
        {
            if (!IsDisposed)
            {
                isDisposed = true;
                Session.StopSessionDisposing();
            }
        }

        public bool IsDisposed { get { return isDisposed; } }
        ~AppServerCore() { Dispose(false); }

        public void AddFactory(IContentGeneratorFactory factory)
        {
            lock ( this.factoriesLock)
            {
                factories.Add(factory);
            }
        }

        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="request">The request.</param>
        public virtual void ProcessRequest(ContentRequest request )
        {
            ContentResponse response = new ContentResponse();
            response.Headers = new Dictionary<string, string>();
            response.Key = request.Key;



            // Session Management
            Session session = null;
            bool sessionNew = false;
            if (request.SessionId != null)
            {
                session = Session.ValidateSession(request.SessionId);
            }

            if (session == null)
            {
                session = new Session(IdGenerator.Create());
                Session.AddSession(session);
                sessionNew = true;
            }

            response.SessionId = session.ID;
            response.SessionIdNew = sessionNew;
            


            IContentGeneratorFactory factory = null;
            lock (this.factoriesLock)
            {
                for (int index = 0; index < factories.Count; ++index)
                {

                    if (factories[index].CanProcessRequest(request))
                    {
                        factory = factories[index];
                        break;
                    }
                }
            }


            if (factory != null)
            {
                IContentGenerator generator = factory.Create(request);
                ContentGeneratorContext context = new ContentGeneratorContext();
                context.Factory = factory;
                context.Request = request;
                generator.Generate(context);
            }
            else
            {
                response.StatusCode = 500;
                processResponse(response);
            }

        }
    }
}
